﻿using System;
using System.Collections.ObjectModel;
using System.Data.Common;
using Unknown.Framework.Develop;
using Unknown.Framework.General;

namespace Unknown.Framework.Database
{
    /// <summary>
    /// 读操作处理抽象类
    /// </summary>
    /// <typeparam name="T">对象</typeparam>
    public abstract class AbstractReaderOperationHandler<T> : IOperationHandler
    {
        /// <summary>
        /// 数据读取器
        /// </summary>
        protected DbDataReader DataReader { get; set; }
        private Collection<string> _Fields = new Collection<string>();
        /// <summary>
        /// 字段集合
        /// </summary>
        protected Collection<string> Fields
        {
            get
            {
                return this._Fields;
            }
        }
        private int _First = 1;
        /// <summary>
        /// 开始行
        /// </summary>
        public int First
        {
            get
            {
                return this._First;
            }
            set
            {
                if (value >= 1)
                {
                    this._First = value;
                }
                else
                {
                    this._First = 1;
                }
            }
        }
        private int _Last = int.MaxValue;
        /// <summary>
        /// 结束行
        /// </summary>
        public int Last
        {
            get
            {
                return this._Last;
            }
            set
            {
                if (value >= 1)
                {
                    this._Last = value;
                }
                else
                {
                    this._Last = int.MaxValue;
                }
            }
        }
        private Collection<T> _Results = new Collection<T>();
        /// <summary>
        /// 结果
        /// </summary>
        public Collection<T> Results
        {
            get
            {
                return this._Results;
            }
        }

        /// <summary>
        /// 字段前缀
        /// </summary>
        public string FieldPrefix { get; set; }

        /// <summary>
        /// 次序
        /// </summary>
        /// <param name="field">字段</param>
        /// <returns>结果</returns>
        protected virtual int Ordinal(string field)
        {
            int result = -1;

            if ((this.DataReader != null) && (this.Fields != null))
            {
                bool isNull = false;

                string currentField = string.Format(Variable.Culture, "{0}{1}", this.FieldPrefix, field);

                if ((!string.IsNullOrEmpty(currentField)) && (this.Fields.Contains(currentField.ToLower(Variable.Culture))))
                {
                    result = this.DataReader.GetOrdinal(currentField);
                    isNull = this.DataReader.IsDBNull(result);
                    if (isNull)
                    {
                        result = -1;
                    }
                }
            }

            return result;
        }

        /// <summary>
        /// 赋值
        /// </summary>
        /// <param name="field">字段</param>
        /// <param name="defaultValue">默认值</param>
        /// <returns>结果</returns>
        protected virtual byte[] AssignBinary(string field, byte[] defaultValue)
        {
            byte[] result = null;

            int ordinal = this.Ordinal(field);
            if (ordinal >= 0)
            {
                object value = this.DataReader.GetValue(ordinal);
                if (value != null)
                {
                    result = value as byte[];
                }
            }
            else
            {
                result = defaultValue;
            }

            return result;
        }

        /// <summary>
        /// 赋值
        /// </summary>
        /// <param name="field">字段</param>
        /// <param name="defaultValue">默认值</param>
        /// <returns>结果</returns>
        protected virtual bool AssignBoolean(string field, bool defaultValue)
        {
            bool result = false;

            int ordinal = this.Ordinal(field);
            if (ordinal >= 0)
            {
                try
                {
                    result = this.DataReader.GetBoolean(ordinal);
                }
                catch (InvalidCastException exception)
                {
                    Collection<string> remarks = new Collection<string>();
                    remarks.Add(field);

                    CrashHandlers.Default.Hibernate(exception, remarks);
                }
            }
            else
            {
                result = defaultValue;
            }

            return result;
        }

        /// <summary>
        /// 赋值
        /// </summary>
        /// <param name="field">字段</param>
        /// <param name="defaultValue">默认值</param>
        /// <returns>结果</returns>
        protected virtual bool? AssignBoolean(string field, bool? defaultValue)
        {
            bool? result = null;

            int ordinal = this.Ordinal(field);
            if (ordinal >= 0)
            {
                try
                {
                    result = this.DataReader.GetBoolean(ordinal);
                }
                catch (InvalidCastException exception)
                {
                    Collection<string> remarks = new Collection<string>();
                    remarks.Add(field);

                    CrashHandlers.Default.Hibernate(exception, remarks);
                }
            }
            else
            {
                result = defaultValue;
            }

            return result;
        }

        /// <summary>
        /// 赋值
        /// </summary>
        /// <param name="field">字段</param>
        /// <param name="defaultValue">默认值</param>
        /// <returns>结果</returns>
        protected virtual decimal AssignDecimal(string field, decimal defaultValue)
        {
            decimal result = 0;

            int ordinal = this.Ordinal(field);
            if (ordinal >= 0)
            {
                try
                {
                    result = this.DataReader.GetDecimal(ordinal);
                }
                catch (InvalidCastException exception)
                {
                    Collection<string> remarks = new Collection<string>();
                    remarks.Add(field);

                    CrashHandlers.Default.Hibernate(exception, remarks);
                }
            }
            else
            {
                result = defaultValue;
            }

            return result;
        }

        /// <summary>
        /// 赋值
        /// </summary>
        /// <param name="field">字段</param>
        /// <param name="defaultValue">默认值</param>
        /// <returns>结果</returns>
        protected virtual decimal? AssignDecimal(string field, decimal? defaultValue)
        {
            decimal? result = null;

            int ordinal = this.Ordinal(field);
            if (ordinal >= 0)
            {
                try
                {
                    result = this.DataReader.GetDecimal(ordinal);
                }
                catch (InvalidCastException exception)
                {
                    Collection<string> remarks = new Collection<string>();
                    remarks.Add(field);

                    CrashHandlers.Default.Hibernate(exception, remarks);
                }
            }
            else
            {
                result = defaultValue;
            }

            return result;
        }

        /// <summary>
        /// 赋值
        /// </summary>
        /// <param name="field">字段</param>
        /// <param name="defaultValue">默认值</param>
        /// <returns>结果</returns>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "integer")]
        protected virtual int AssignInteger(string field, int defaultValue)
        {
            int result = 0;

            int ordinal = this.Ordinal(field);
            if (ordinal >= 0)
            {
                try
                {
                    result = this.DataReader.GetInt32(ordinal);
                }
                catch (InvalidCastException exception)
                {
                    Collection<string> remarks = new Collection<string>();
                    remarks.Add(field);

                    CrashHandlers.Default.Hibernate(exception, remarks);
                }
            }
            else
            {
                result = defaultValue;
            }

            return result;
        }

        /// <summary>
        /// 赋值
        /// </summary>
        /// <param name="field">字段</param>
        /// <param name="defaultValue">默认值</param>
        /// <returns>结果</returns>
        protected virtual int? AssignInteger(string field, int? defaultValue)
        {
            int? result = null;

            int ordinal = this.Ordinal(field);
            if (ordinal >= 0)
            {
                try
                {
                    result = this.DataReader.GetInt32(ordinal);
                }
                catch (InvalidCastException exception)
                {
                    Collection<string> remarks = new Collection<string>();
                    remarks.Add(field);

                    CrashHandlers.Default.Hibernate(exception, remarks);
                }
            }
            else
            {
                result = defaultValue;
            }

            return result;
        }

        /// <summary>
        /// 赋值
        /// </summary>
        /// <param name="field">字段</param>
        /// <param name="defaultValue">默认值</param>
        /// <returns>结果</returns>
        protected virtual long AssignNumber(string field, long defaultValue)
        {
            long result = 0;

            int ordinal = this.Ordinal(field);
            if (ordinal >= 0)
            {
                try
                {
                    result = this.DataReader.GetInt64(ordinal);
                }
                catch (InvalidCastException exception)
                {
                    Collection<string> remarks = new Collection<string>();
                    remarks.Add(field);

                    CrashHandlers.Default.Hibernate(exception, remarks);
                }
            }
            else
            {
                result = defaultValue;
            }

            return result;
        }

        /// <summary>
        /// 赋值
        /// </summary>
        /// <param name="field">字段</param>
        /// <param name="defaultValue">默认值</param>
        /// <returns>结果</returns>
        protected virtual long? AssignNumber(string field, long? defaultValue)
        {
            long? result = null;

            int ordinal = this.Ordinal(field);
            if (ordinal >= 0)
            {
                try
                {
                    result = this.DataReader.GetInt64(ordinal);
                }
                catch (InvalidCastException exception)
                {
                    Collection<string> remarks = new Collection<string>();
                    remarks.Add(field);

                    CrashHandlers.Default.Hibernate(exception, remarks);
                }
            }
            else
            {
                result = defaultValue;
            }

            return result;
        }

        /// <summary>
        /// 赋值
        /// </summary>
        /// <param name="field">字段</param>
        /// <param name="defaultValue">默认值</param>
        /// <returns>结果</returns>
        protected virtual string AssignString(string field, string defaultValue)
        {
            string result = null;

            int ordinal = this.Ordinal(field);
            if (ordinal >= 0)
            {
                try
                {
                    result = this.DataReader.GetString(ordinal);
                }
                catch (InvalidCastException exception)
                {
                    Collection<string> remarks = new Collection<string>();
                    remarks.Add(field);

                    CrashHandlers.Default.Hibernate(exception, remarks);
                }
            }
            else
            {
                result = defaultValue;
            }

            return result;
        }

        /// <summary>
        /// 赋值
        /// </summary>
        /// <param name="field">字段</param>
        /// <param name="defaultValue">默认值</param>
        /// <returns>结果</returns>
        protected virtual object AssignObject(string field, object defaultValue)
        {
            object result = null;

            int ordinal = this.Ordinal(field);
            if (ordinal >= 0)
            {
                result = this.DataReader.GetValue(ordinal);
            }
            else
            {
                result = defaultValue;
            }

            return result;
        }

        /// <summary>
        /// 赋值
        /// </summary>
        /// <param name="field">字段</param>
        /// <param name="defaultValue">默认值</param>
        /// <returns>结果</returns>
        protected virtual DateTime AssignTime(string field, DateTime defaultValue)
        {
            DateTime result = DateTime.MinValue;

            int ordinal = this.Ordinal(field);
            if (ordinal >= 0)
            {
                try
                {
                    result = this.DataReader.GetDateTime(ordinal);
                }
                catch (InvalidCastException exception)
                {
                    Collection<string> remarks = new Collection<string>();
                    remarks.Add(field);

                    CrashHandlers.Default.Hibernate(exception, remarks);
                }
            }
            else
            {
                result = defaultValue;
            }

            return result;
        }

        /// <summary>
        /// 赋值
        /// </summary>
        /// <param name="field">字段</param>
        /// <param name="defaultValue">默认值</param>
        /// <returns>结果</returns>
        protected virtual DateTime? AssignTime(string field, DateTime? defaultValue)
        {
            DateTime? result = null;

            int ordinal = this.Ordinal(field);
            if (ordinal >= 0)
            {
                try
                {
                    result = this.DataReader.GetDateTime(ordinal);
                }
                catch (InvalidCastException exception)
                {
                    Collection<string> remarks = new Collection<string>();
                    remarks.Add(field);

                    CrashHandlers.Default.Hibernate(exception, remarks);
                }
            }
            else
            {
                result = defaultValue;
            }

            return result;
        }

        /// <summary>
        /// 初始化
        /// </summary>
        protected virtual void Initialize()
        {
            for (int i = 0; i < this.DataReader.FieldCount; i++)
            {
                string field = this.DataReader.GetName(i).ToLower(Variable.Culture);
                this.Fields.Add(field);
            }
        }

        /// <summary>
        /// 转换前
        /// </summary>
        protected virtual void Before()
        {
        }

        /// <summary>
        /// 转换
        /// </summary>
        /// <returns>结果</returns>
        protected virtual T Transform()
        {
            T result = default(T);

            return result;
        }

        /// <summary>
        /// 转换后
        /// </summary>
        protected virtual void After()
        {
        }

        /// <summary>
        /// 空
        /// </summary>
        protected virtual void Empty()
        {
        }

        /// <summary>
        /// 执行
        /// </summary>
        /// <param name="command">命令</param>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
        public void Execute(DbCommand command)
        {
            if (command != null)
            {
                Exception error = null;
                try
                {
                    this.DataReader = command.ExecuteReader();
                    if ((this.DataReader != null) && (this.DataReader.HasRows))
                    {
                        this.Initialize();

                        this.Before();

                        int count = 0;
                        while (this.DataReader.Read())
                        {
                            count++;
                            if ((this.First <= count) && (count <= this.Last))
                            {
                                T entity = this.Transform();
                                if (entity != null)
                                {
                                    this.Results.Add(entity);
                                }
                            }
                            if (count > this.Last)
                            {
                                break;
                            }
                        }

                        this.After();
                    }
                    else
                    {
                        this.Empty();
                    }
                }
                catch (Exception exception)
                {
                    error = exception;
                }
                finally
                {
                    if (this.DataReader != null)
                    {
                        this.DataReader.Close();
                    }
                }

                if (error != null)
                {
                    throw error;
                }
            }
        }
    }
}
